<?php /*
==================================================
TextCMS -- simple plain/text CMS with GPL licence
Administration module
(c) 2008, 4X_Pro
Visit us online: http://textcms.ru
==================================================
*/

define('TextCMS_Admin',1);

admin_main();

/** Основная функция АдминЦентра. Подключает файл index.php, вызывает из него
общую процедуру инициализации cms_init.
**/
function admin_main() {
  if (!include('index.php')) {
    header($_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error');
    echo 'Ошибка: index.php отсутствует или недоступен для чтения!';
    exit();
  }
  cms_init();

  $action = isset($_REQUEST['a']) ? $_REQUEST['a'] : 'admstart_main';

  $GLOBALS['status']=200;
  $GLOBALS['lastmod']=time();
  $GLOBALS['pagedata']['template']='default';
  $content='';

  session_start('TextCMS_admin');
  $auth=false;
  $rkey=md5($GLOBALS['config']['login'].'-'.$GLOBALS['config']['password']);
  if (isset($_POST['cms_login']) && isset($_POST['cms_password'])) {
    
    /* Защита от brute-foce АдминЦентра. Проверяем, что последняя попытка входа была не менее 3 секунд назад */
    $lasttime=0;
    $lastfile=cms_basedir().'/lastlog.txt';
    if (file_exists($lastfile) && is_writable($lastfile)) {
      $fh=fopen($lastfile,'r');
      $lasttime=trim(fgets($fh));
      fclose($fh);
    }
    $curtime=time();
    $fh=fopen($lastfile,'w');
    fputs($fh,$curtime);
    fclose($fh);

    if ($curtime>$lasttime+3) {
      if ($_POST['cms_login']==$GLOBALS['config']['login'] && $_POST['cms_password']==$GLOBALS['config']['password']) {
        $_SESSION['admin_mode']=1;
        $_SESSION['key']=md5($GLOBALS['config']['login'].'-'.$GLOBALS['config']['password']);
        $auth=true;
      }
      else $content.='<div class="errmsg">Неправильный пароль или имя пользователя!</div>';
    }
    else $content.='<div class="errmsg">Вы можете повторить попытку входа не ранее, чем через 3 секунды после предыдущей!</div>';
  }
  elseif (isset($_SESSION['admin_mode']) && ($_SESSION['admin_mode']==1)) $auth=($_SESSION['key']==$rkey);
  if ($auth) {
    $content = cms_call($action);
    if (!$content) $content='Ошибка: указанный модуль или процедура не существует или работает некорректно!';
    $admin_menu = admin_menu();
  }
  else {
    $content.=cms_call('admstart_login');
    $admin_menu='';
  }
  if ($content===false) $GLOBALS['status']=404;

  cms_output($content,$admin_menu);
  ob_flush();
}

/** Используется для сортировки пунктов меню, не должна вызываться напрямую **/
function _admin_menu_sort($a,$b) {
  if (strpos($a,':')!==false) list($proc_name,$num_a,$description)=explode(':',$a,3);
  else $num_a=0;
  if (strpos($b,':')!==false) list($proc_name,$num_b,$description)=explode(':',$b,3);
  else $num_b=0;
  return $num_a-$num_b;
}

/** Обходит все модули и строит административное меню на основе данных в файлах
menu.txt в модулях.
Файл menu.txt состоит из одной или нескольких строк, имеющих такой формат:
proc_name:sort:description
где proc_name -- имя процедуры, которая будет вызвана
sort -- порядок сортировки (пункты с большими номерами идут в конец меню)
description -- описание пункта меню
**/
function admin_menu() {
  $menufiles = admin_iterate_modules('menu.txt');
  $menuitems=array();
  for ($i=0, $count=count($menufiles); $i<$count; $i++) {
    $fh=fopen($menufiles[$i],'r');
    if ($fh) {
      while ($buffer=fgets($fh)) $menuitems[]=$buffer;
      fclose($fh);
    }
  }
  usort($menuitems,'_admin_menu_sort');
  $result='';
  for ($i=0, $count=count($menuitems); $i<$count; $i++) {
    if (strpos($menuitems[$i],':')!==false) {
      list($proc_name,$num,$description)=explode(':',$menuitems[$i],3);
      $result.='<li><a href="admin.php?a='.$proc_name.'">'.trim($description).'</a></li> ';
    }
  }
  if ($count) $result='<ul style="list-style-type: none">'.$result.'</ul>';
  return $result;
}

/** Обходит все подкаталоги модулей в поисках указанного файла.
Возвращает массив имен модулей, в которых этот файл есть. Если имя файла пусто,
возвращает все модули вообще. **/
function admin_iterate_modules($filename) {
  $result = array();
  if (!cms_valid_file($filename,false,false)) {
    _dbg('Имя файла содержит некорректные символы!');
    return $result;
  }
  if (!is_dir('modules')) {
    _dbg('Каталог modules не найден!');
    return $result;
  }
  $dh=opendir('modules');
  while ($curname=readdir($dh)) if ($curname!='.' && $curname!='..' && is_dir('modules/'.$curname)) {
    if (is_file('modules/'.$curname.'/'.$filename)) $result[]='modules/'.$curname.'/'.$filename;
  }
  closedir($dh);
  return $result;
}
